package com.arch.dev.server;

import java.io.File;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.Calendar;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.TimeZone;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.flex.remoting.RemotingDestination;
import org.springframework.flex.remoting.RemotingInclude;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.arch.dev.client.GreetingService;
import com.arch.dev.client.vo.AuthorityVO;
import com.arch.dev.client.vo.BaseVO;
import com.arch.dev.client.vo.BudgetVO;
import com.arch.dev.client.vo.CatagoryVO;
import com.arch.dev.client.vo.MonthVO;
import com.arch.dev.client.vo.PdfVO;
import com.arch.dev.client.vo.UserVO;
import com.arch.dev.client.vo.YearVO;
import com.arch.dev.server.bean.AbstractTimestampEntity;
import com.arch.dev.server.bean.Authority;
import com.arch.dev.server.bean.Budget;
import com.arch.dev.server.bean.Catagory;
import com.arch.dev.server.bean.Pdf;
import com.arch.dev.server.bean.User;
import com.arch.dev.server.dao.BudgetDao;
import com.arch.dev.server.dao.CatagoryDao;
import com.arch.dev.server.dao.PdfDao;
import com.arch.dev.server.dao.UserDao;
import com.arch.dev.server.pdf.FirstPdf;
import com.arch.dev.server.util.BudgetCalcUtil;
import com.arch.dev.server.util.FileUploadUtil;

@Service("budgetService")
@RemotingDestination(channels={"my-amf","my-secure-amf"})
public class GreetingServiceImpl implements GreetingService {
	
	Logger logger = Logger.getLogger(GreetingServiceImpl.class);
	
	class BudgetRecordComparator implements Comparator<Budget> {

		@Override
		public int compare(Budget o1, Budget o2) {

			if (o1.getLastUpdated().before(o2.getLastUpdated())) {

				return 1;

			} else if (o1.getLastUpdated().after(o2.getLastUpdated())) {

				return -1;

			} else {

				return 0;

			}
		}

	}

	@Autowired
	BudgetDao budgetDao;

	@Autowired
	CatagoryDao catagoryDao;

	@Autowired
	PdfDao pdfDao;
	
	@Autowired
	UserDao userDao;

	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	public List<BudgetVO> getAllValues() throws Exception {

		List<Budget> budgets = budgetDao.getAllValues();
		
		Collections.sort(budgets, new ModifiedDateComparator());
		
		List<BudgetVO> budgetVOs = new ArrayList<BudgetVO>(budgets.size());

		for (Budget budget : budgets) {

			BudgetVO budgetVO = new BudgetVO();

			budgetVO.setId(budget.getId());

			budgetVO.setDate(budget.getDate());

			budgetVO.setTitle(budget.getDescription());

			budgetVO.setCost(budget.getCost());
			
			budgetVO.setCreatedDate(budget.getCreatedDate());
			
			budgetVO.setLastUpdated(budget.getLastUpdated());

			Catagory catagory = budget.getCatagory();

			CatagoryVO catagoryVO = new CatagoryVO();

			catagoryVO.setId(catagory.getId());

			catagoryVO.setName(catagory.getName());
			
			catagoryVO.setCreatedDate(catagory.getCreatedDate());
			
			catagoryVO.setLastUpdated(catagory.getLastUpdated());

			budgetVO.setCatagoryVO(catagoryVO);

			budgetVOs.add(budgetVO);

		}

		return budgetVOs;

	}
	
	@RemotingInclude
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	public List<CatagoryVO> getAllCatagories() throws Exception {

		List<Catagory> catagories = catagoryDao.getAllValues();

		List<CatagoryVO> catagoryVOs = new ArrayList<CatagoryVO>(
				catagories.size());

		for (Catagory catagory : catagories) {

			CatagoryVO catagoryVO = new CatagoryVO();

			catagoryVO.setId(catagory.getId());

			catagoryVO.setName(catagory.getName());
	
			catagoryVO.setCreatedDate(catagory.getCreatedDate());
			
			catagoryVO.setLastUpdated(catagory.getLastUpdated());

			catagoryVOs.add(catagoryVO);

		}

		return catagoryVOs;

	}

	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	public void persistCatagoryValues(CatagoryVO catagoryVO) throws Exception {

		Catagory catagory = new Catagory();
		if (catagoryVO.getId() != null) {
			catagory.setId(catagoryVO.getId());
		}
		if (catagoryVO.getCreatedDate() != null) {
			catagory.setCreatedDate(catagoryVO.getCreatedDate());
		}
		if (catagoryVO.getLastUpdated() != null) {
			catagory.setLastUpdated(catagoryVO.getLastUpdated());
		}
		catagory.setName(catagoryVO.getName());
		catagoryDao.saveCatagory(catagory);

	}
	
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	public void persistValues(BudgetVO budgetVO) throws Exception {

		logger.info("****************" + TimeZone.getDefault());
		
		Budget budget = new Budget();
		if(budgetVO.getId() != null){
			budget.setId(budgetVO.getId());
		}
		
		budget.setDescription(budgetVO.getTitle());
		
		logger.info("**************** date " + budgetVO.getDate());
		
		budget.setDate(budgetVO.getDate());

		logger.info("**************** date ***" + budget.getDate());
		
		budget.setCost(budgetVO.getCost());
		
		if(budgetVO.getCreatedDate()!= null){
			budget.setCreatedDate(budgetVO.getCreatedDate());
		}
		
		if(budgetVO.getLastUpdated() != null){
			budget.setLastUpdated(budgetVO.getLastUpdated());
		}		

		Catagory catagory = new Catagory();

		catagory.setId(budgetVO.getCatagoryVO().getId());

		catagory.setName(budgetVO.getCatagoryVO().getName());

		budget.setCatagory(catagory);		

		budgetDao.saveBudget(budget);

	}


	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	public void deleteValues(Set<BudgetVO> budgetVOs) throws Exception {
			for (BudgetVO budgetVO : budgetVOs) {
			Budget budget = new Budget();
			budget.setId(budgetVO.getId());
			budgetDao.removeBudget(budget);

		}

	}
	
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	public void deleteCatagoryValues(Set<CatagoryVO> catagoryVOs) throws Exception {

		for (CatagoryVO catagoryVO : catagoryVOs) {

			Catagory catagory = new Catagory();

			catagory.setId(catagoryVO.getId());

			catagoryDao.removeCatagory(catagory);

		}

	}

	public List<BudgetVO> getMonthlyConsolidatedData(List<BudgetVO> budgetVOs)
			throws Exception {

		// List<BudgetVO> budgetVOs = getAllValues();

	

		BigDecimal totalCost = new BigDecimal(0);

		BudgetVO previousBudgetVO = null;

		List<BudgetVO> totalCountBudgetVO = new ArrayList();

		Iterator<BudgetVO> it = budgetVOs.iterator();

		while (it.hasNext()) {

			BudgetVO budgetVO = it.next();

			if (previousBudgetVO != null
					&& !previousBudgetVO.getDate().equals(budgetVO.getDate())) {

				BudgetVO bdgVO = new BudgetVO();

				bdgVO.setCost(totalCost);

				bdgVO.setDate(previousBudgetVO.getDate());

				totalCountBudgetVO.add(bdgVO);

				previousBudgetVO = budgetVO;

				totalCost = previousBudgetVO.getCost();

				if (!it.hasNext()) {

					bdgVO = new BudgetVO();

					bdgVO.setCost(previousBudgetVO.getCost());

					bdgVO.setDate(previousBudgetVO.getDate());

					totalCountBudgetVO.add(bdgVO);

				}

			} else {

				totalCost = totalCost.add(budgetVO.getCost());

				if (!it.hasNext()) {

					BudgetVO bdgVO = new BudgetVO();

					bdgVO.setCost(totalCost);

					bdgVO.setDate(budgetVO.getDate());

					totalCountBudgetVO.add(bdgVO);

				}

				previousBudgetVO = budgetVO;

			}

		}

		return totalCountBudgetVO;

	}

	@RemotingInclude
	public Set<YearVO> getDateData() throws Exception {

		List<BudgetVO> budgetVOs = getAllValues();

		Set<YearVO> years = new HashSet<YearVO>();

		for (BudgetVO budgetVO : budgetVOs) {

			Calendar cl = Calendar.getInstance();

			cl.setTime(budgetVO.getDate());

			int date = cl.get(Calendar.DATE);

			int year = cl.get(Calendar.YEAR);

			int month = cl.get(Calendar.MONTH);

			YearVO yearVO = getYearVOFromSet(years, year);

			if (yearVO == null) {

				yearVO = new YearVO(year, Integer.toString(year));

				years.add(yearVO);

			}

			Set<MonthVO> months = yearVO.getMonths();

			if (months == null) {

				months = new HashSet<MonthVO>();

				yearVO.setMonths(months);

			}

			MonthVO monthVO = getMonthVOFromSet(months, month);

			if (monthVO == null) {

				monthVO = new MonthVO();

				monthVO.setId(month);

				months.add(monthVO);

			}

			Set<Integer> dates = monthVO.getDates();

			if (dates == null) {

				dates = new HashSet<Integer>();

				monthVO.setDates(dates);

			}

			dates.add(date);

		}

		return years;

	}

	private YearVO getYearVOFromSet(Set<YearVO> years, int year) {

		for (YearVO yearVO : years) {

			if (yearVO.getId() == year) {

				return yearVO;

			}

		}

		return null;

	}

	private MonthVO getMonthVOFromSet(Set<MonthVO> months, int month) {

		for (MonthVO monthVO : months) {

			if (monthVO.getId() == month) {

				return monthVO;

			}

		}

		return null;

	}

	@RemotingInclude
	public List<BudgetVO> getMonthlyDataForYear(int year, int month, boolean isConsolidated)
			throws Exception {

		Calendar cl = Calendar.getInstance();

		cl = Calendar.getInstance();

		cl.clear();

		cl.set(Calendar.YEAR, year);

		cl.set(Calendar.MONTH, month);

		cl.set(Calendar.DATE, cl.getActualMinimum(Calendar.DATE));

		Date startDate = cl.getTime();

		logger.info(startDate);

		cl.clear();

		cl.set(Calendar.YEAR, year);

		cl.set(Calendar.MONTH, month);

		cl.set(Calendar.DATE, cl.getActualMaximum(Calendar.DATE));

		Date endDate = cl.getTime();

		logger.info(endDate);

		List<Budget> budgets = budgetDao
				.getDataBetweenDates(startDate, endDate);

		List<BudgetVO> budgetVOs = new ArrayList<BudgetVO>(budgets.size());

		for (Budget budget : budgets) {

			BudgetVO budgetVO = new BudgetVO();

			budgetVO.setId(budget.getId());

			budgetVO.setDate(budget.getDate());

			budgetVO.setTitle(budget.getDescription());

			budgetVO.setCost(budget.getCost());			
			
			budgetVO.setCreatedDate(budget.getCreatedDate());
			
			budgetVO.setLastUpdated(budget.getLastUpdated());

			Catagory catagory = budget.getCatagory();

			CatagoryVO catagoryVO = new CatagoryVO();

			catagoryVO.setId(catagory.getId());

			catagoryVO.setName(catagory.getName());
			
			catagoryVO.setCreatedDate(catagory.getCreatedDate());
			
			catagoryVO.setLastUpdated(catagory.getLastUpdated());

			budgetVO.setCatagoryVO(catagoryVO);

			budgetVOs.add(budgetVO);

		}
		
		Comparator<BudgetVO> dataComparator = new Comparator<BudgetVO>() {

			public int compare(BudgetVO o1, BudgetVO o2) {

				if (o1.getDate().before(o2.getDate())) {

					return -1;

				} else if (o1.getDate().after(o2.getDate())) {

					return 1;

				} else {

					return 0;

				}

			}

		};

		Collections.sort(budgetVOs, dataComparator);
		
		if(isConsolidated){
			return getMonthlyConsolidatedData(budgetVOs);
		}else{
			return budgetVOs;
		}
		

	}

	public PdfVO generatePDF() throws Exception {

		ArrayList<BudgetVO> budgetVOs = (ArrayList<BudgetVO>) getAllValues();

		FirstPdf firstPDF = new FirstPdf();

		Calendar cl = Calendar.getInstance();

		Date date = cl.getTime();

		Long time = cl.getTimeInMillis();

		String pdfName = "MONTHLY_PDF_" + time;

		File file = new File("PDF/" + pdfName + ".pdf");

		logger.info(file.getAbsolutePath());

	//	firstPDF.generatePDF(file, budgetVOs);

		Pdf pdf = new Pdf();

		pdf.setDate(date);

		pdf.setName(pdfName);

		pdfDao.savePdf(pdf);

		PdfVO pdfVO = new PdfVO(pdfName, date);

		return pdfVO;

	}

	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	public List<PdfVO> getAllPDFValues() throws Exception {

		List<Pdf> pdfs = pdfDao.getAllValues();		
		
		Collections.sort(pdfs, new ModifiedDateComparator());

		List<PdfVO> pdfVOs = new ArrayList<PdfVO>(pdfs.size());

		for (Pdf pdf : pdfs) {

			PdfVO pdfVO = new PdfVO();

			pdfVO.setId(pdf.getId());

			pdfVO.setDate(pdf.getDate());

			pdfVO.setName(pdf.getName());

			pdfVOs.add(pdfVO);

		}		
		
		return pdfVOs;

	}

	public List<BudgetVO> getDataForDate(Date selectedDate) {

		List<Date> dates = new ArrayList<Date>();
		dates.add(selectedDate);

		List<Budget> budgets = budgetDao.getDataForDate(dates);
		
		Collections.sort(budgets, new BudgetRecordComparator());
		
		List<BudgetVO> budgetVOs = new ArrayList<BudgetVO>(budgets.size());

		for (Budget budget : budgets) {

			BudgetVO budgetVO = new BudgetVO();

			budgetVO.setId(budget.getId());

			budgetVO.setDate(budget.getDate());

			budgetVO.setTitle(budget.getDescription());

			budgetVO.setCost(budget.getCost());
			
			budgetVO.setCreatedDate(budget.getCreatedDate());
			
			budgetVO.setLastUpdated(budget.getLastUpdated());

			Catagory catagory = budget.getCatagory();

			CatagoryVO catagoryVO = new CatagoryVO();

			catagoryVO.setId(catagory.getId());

			catagoryVO.setName(catagory.getName());
			
			catagoryVO.setCreatedDate(catagory.getCreatedDate());
			
			catagoryVO.setLastUpdated(catagory.getLastUpdated());

			budgetVO.setCatagoryVO(catagoryVO);

			budgetVOs.add(budgetVO);

		}

		return budgetVOs;

	}

	public List<BudgetVO> getYearlyConsolidatedData(List<BudgetVO> budgetVOs)
			throws Exception {

		

		BigDecimal totalCost = new BigDecimal(0);

		BudgetVO previousBudgetVO = null;

		int currentMonth = -1;

		List<BudgetVO> totalCountBudgetVO = new ArrayList();

		Iterator<BudgetVO> it = budgetVOs.iterator();

		while (it.hasNext()) {

			BudgetVO budgetVO = it.next();

			currentMonth = getMonthFromDate(budgetVO.getDate());

			if (previousBudgetVO != null
					&& getMonthFromDate(previousBudgetVO.getDate()) != currentMonth) {

				BudgetVO bdgVO = new BudgetVO();

				bdgVO.setCost(totalCost);

				bdgVO.setDate(previousBudgetVO.getDate());

				totalCountBudgetVO.add(bdgVO);

				previousBudgetVO = budgetVO;

				totalCost = previousBudgetVO.getCost();

				if (!it.hasNext()) {

					bdgVO = new BudgetVO();

					bdgVO.setCost(previousBudgetVO.getCost());

					bdgVO.setDate(previousBudgetVO.getDate());

					totalCountBudgetVO.add(bdgVO);

				}

			} else {

				totalCost = totalCost.add(budgetVO.getCost());

				if (!it.hasNext()) {

					BudgetVO bdgVO = new BudgetVO();

					bdgVO.setCost(totalCost);

					bdgVO.setDate(budgetVO.getDate());

					totalCountBudgetVO.add(bdgVO);

				}

				previousBudgetVO = budgetVO;

			}

		}

		return totalCountBudgetVO;

	}

	@RemotingInclude
	public List<BudgetVO> getYearlyData(int year, boolean isConsolidated) throws Exception {

		Calendar cl = Calendar.getInstance();

		cl = Calendar.getInstance();

		cl.clear();

		cl.set(Calendar.YEAR, year);

		cl.set(Calendar.MONTH, cl.getActualMinimum(Calendar.MONTH));

		cl.set(Calendar.DATE, cl.getActualMinimum(Calendar.DATE));

		Date startDate = cl.getTime();

		logger.info(startDate);

		cl.clear();

		cl.set(Calendar.YEAR, year);

		cl.set(Calendar.MONTH, cl.getActualMaximum(Calendar.MONTH));

		cl.set(Calendar.DATE, cl.getActualMaximum(Calendar.DATE));

		Date endDate = cl.getTime();

		logger.info(endDate);

		List<Budget> budgets = budgetDao
				.getDataBetweenDates(startDate, endDate);

		List<BudgetVO> budgetVOs = new ArrayList<BudgetVO>(budgets.size());

		for (Budget budget : budgets) {

			BudgetVO budgetVO = new BudgetVO();

			budgetVO.setId(budget.getId());

			budgetVO.setDate(budget.getDate());

			budgetVO.setTitle(budget.getDescription());

			budgetVO.setCost(budget.getCost());
			
			budgetVO.setCreatedDate(budget.getCreatedDate());
			
			budgetVO.setLastUpdated(budget.getLastUpdated());

			Catagory catagory = budget.getCatagory();

			CatagoryVO catagoryVO = new CatagoryVO();

			catagoryVO.setId(catagory.getId());

			catagoryVO.setName(catagory.getName());
			
			catagoryVO.setCreatedDate(catagory.getCreatedDate());
			
			catagoryVO.setLastUpdated(catagory.getLastUpdated());

			budgetVO.setCatagoryVO(catagoryVO);

			budgetVOs.add(budgetVO);

		}
		
		Comparator<BudgetVO> dateComparator = new Comparator<BudgetVO>() {

			
			public int compare(BudgetVO o1, BudgetVO o2) {

				if (o1.getDate().before(o2.getDate())) {

					return -1;

				} else if (o1.getDate().after(o2.getDate())) {

					return 1;

				} else {

					return 0;

				}

			}

		};

		Collections.sort(budgetVOs, dateComparator);

		if(isConsolidated){
			return getYearlyConsolidatedData(budgetVOs);
		}else{
			return budgetVOs;
		}
		

	}

	private int getMonthFromDate(Date date) {

		Calendar cl = Calendar.getInstance();

		cl.clear();

		cl.setTime(date);

		return cl.get(Calendar.MONTH);

	}
	
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	public PdfVO savePDF(PdfVO pdfVO) throws Exception {
		Pdf pdf = new Pdf();

		pdf.setDate(pdfVO.getDate());

		pdf.setName(pdfVO.getName());

		pdfDao.savePdf(pdf);

		pdfVO = new PdfVO(pdf.getName(), pdf.getDate());

		return pdfVO;

	}

	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	public void deletePDF(Set<PdfVO> pdfVOs) throws Exception {

		for (PdfVO pdfVO : pdfVOs) {

			Pdf pdf = new Pdf();

			pdf.setId(pdfVO.getId());

			pdfDao.removePdf(pdf);

		}

		
	}

	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	public void processDataFromExcel(String excelFileName) throws Exception {
		
		File file = new File(excelFileName);
		ArrayList<BudgetVO> budgets = FileUploadUtil
				.ProcessExcelData(file);
		List<CatagoryVO> catagoryVOs = getAllCatagories();
		boolean found = false;
		for (int i = 0; i < budgets.size(); i++) {
			BudgetVO budgetVO = budgets.get(i);
			CatagoryVO catagoryVO = budgetVO.getCatagoryVO();
			found = false;
			for (CatagoryVO ctyVOs : catagoryVOs) {

				if (ctyVOs.getName().equalsIgnoreCase(catagoryVO.getName())) {
					catagoryVO.setId(ctyVOs.getId());
					found = true;
					break;
				}

			}

			if (found) {
				persistValues(budgetVO);
			}

		}

	}

	@Override
	public List<UserVO> getAllUserValues() throws Exception {	 
				
			List<User> users = userDao.getAllValues();
			
		
			List<UserVO> usersVO = new ArrayList<UserVO>();
			
			for (User user : users) {
				UserVO userVO = new UserVO();
				AuthorityVO authorityVO= new AuthorityVO();
				userVO.setUserName(user.getUserName());
				userVO.setPassWord(user.getPassWord());
				userVO.setEnabled(user.getEnabled());
				authorityVO.setUserName(user.getAuthority().getUserName());
				authorityVO.setAuthority(user.getAuthority().getAuthority());
				authorityVO.setCreatedDate(user.getAuthority().getCreatedDate());
				authorityVO.setLastUpdated(user.getAuthority().getLastUpdated());
				userVO.setAuthorityVO(authorityVO);
				userVO.setCreatedDate(user.getCreatedDate());
				userVO.setLastUpdated(user.getLastUpdated());
				usersVO.add(userVO);
			}
	
			return usersVO;
	}



	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	public void persistUserValues(UserVO userVO) throws Exception {
		User user = new User();
		user.setUserName(userVO.getUserName());				
		user.setEnabled(userVO.getEnabled());
		Authority auth= new Authority();
		auth.setUserName(userVO.getAuthorityVO().getUserName());
		auth.setAuthority(userVO.getAuthorityVO().getAuthority());
		user.setAuthority(auth);
		if(userVO.getLastUpdated() != null){
			user.setLastUpdated(userVO.getLastUpdated());
			auth.setLastUpdated(userVO.getAuthorityVO().getLastUpdated());
		}
		if(userVO.getCreatedDate()!= null){
			user.setCreatedDate(userVO.getCreatedDate());
			auth.setCreatedDate(userVO.getAuthorityVO().getCreatedDate());
			user.setPassWord(userVO.getPassWord());
		}else{
			user.setPassWord(BudgetCalcUtil.encryptPassword(userVO.getPassWord()));
		}		
		userDao.saveUser(user);

	}
	
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	public void deleteUserValues(Set<UserVO> userVOs) throws Exception {
		for (UserVO userVO : userVOs) {
			User user = new User();
			Authority auth= new Authority();
			auth.setUserName(userVO.getAuthorityVO().getUserName());
			user.setUserName(userVO.getUserName());
			user.setAuthority(auth);
			userDao.removeUser(user);
		}
	}
	
	
	@RemotingInclude
	public List<BudgetVO> getCatagoryWiseDataForMonth(int year, int month, boolean isConsolidated) throws Exception{
		List<BudgetVO> monthlyDataBudgetVOList= getMonthlyDataForYear(year, month, false);
		Collections.sort(monthlyDataBudgetVOList, new Comparator<BudgetVO>(){
			@Override
			public int compare(BudgetVO arg0, BudgetVO arg1) {
				return arg0.getCatagoryVO().getName().compareTo(arg1.getCatagoryVO().getName());
			}
			
		});
	
		if(isConsolidated){
			return getCategoryConsolidatedData(monthlyDataBudgetVOList);
		}else{
			return monthlyDataBudgetVOList;
		}
	
	}
	
	public List<BudgetVO> getCategoryConsolidatedData(List<BudgetVO> budgetVOs)
			throws Exception {
		
		BigDecimal totalCost = new BigDecimal(0);

		BudgetVO previousBudgetVO = null;

		List<BudgetVO> totalCountBudgetVO = new ArrayList();

		Iterator<BudgetVO> it = budgetVOs.iterator();

		while (it.hasNext()) {

			BudgetVO budgetVO = it.next();

			if (previousBudgetVO != null
					&& !previousBudgetVO.getCatagoryVO().getName().equals(budgetVO.getCatagoryVO().getName())) {

				BudgetVO bdgVO = new BudgetVO();

				bdgVO.setCost(totalCost);

				bdgVO.setDate(previousBudgetVO.getDate());
				
				bdgVO.setCatagoryVO(previousBudgetVO.getCatagoryVO());

				totalCountBudgetVO.add(bdgVO);

				previousBudgetVO = budgetVO;

				totalCost = previousBudgetVO.getCost();

				if (!it.hasNext()) {

					bdgVO = new BudgetVO();

					bdgVO.setCost(previousBudgetVO.getCost());

					bdgVO.setDate(previousBudgetVO.getDate());
					
					bdgVO.setCatagoryVO(previousBudgetVO.getCatagoryVO());

					totalCountBudgetVO.add(bdgVO);

				}

			} else {

				totalCost = totalCost.add(budgetVO.getCost());

				if (!it.hasNext()) {

					BudgetVO bdgVO = new BudgetVO();

					bdgVO.setCost(totalCost);

					bdgVO.setDate(budgetVO.getDate());
					
					bdgVO.setCatagoryVO(budgetVO.getCatagoryVO());

					totalCountBudgetVO.add(bdgVO);

				}

				previousBudgetVO = budgetVO;

			}

		}

		return totalCountBudgetVO;
	}
	
	@RemotingInclude
	public List<List<BudgetVO>> getMonthlyCatagoryWiseDataForYear(int year, List<MonthVO> monthVOList, boolean isConsolidated) throws Exception{
		List<List<BudgetVO>> yearlyBudgetVOList = new ArrayList<List<BudgetVO>>();
		List<BudgetVO> monthlyBudgetVOList = null;
		for (MonthVO monthVO : monthVOList) {
			 monthlyBudgetVOList = getCatagoryWiseDataForMonth(year, monthVO.getId(), isConsolidated);
			 yearlyBudgetVOList.add(monthlyBudgetVOList);
		}		
		return yearlyBudgetVOList;	
	}
	
	
	class ModifiedDateComparator implements Comparator<AbstractTimestampEntity>{
		
		@Override
		public int compare(AbstractTimestampEntity o1, AbstractTimestampEntity o2) {

			if (o1.getLastUpdated().before(o2.getLastUpdated())) {

				return 1;

			} else if (o1.getLastUpdated().after(o2.getLastUpdated())) {

				return -1;

			} else {

				return 0;

			}
		}

	}
	

	

}
